#include <iostream>
#include <fstream>
extern "C"
{
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}

using namespace std;

#define YUV_FILE "400_300_25.yuv"
#define RGB_FILE "800_600_25.rgba"
int main(int argc, char *argv[])
{
    cout << "ffmpeg version " << av_version_info() << endl;
    int width = 400;
    int height = 300;
    int rgb_width = 800;
    int rgb_height = 600;
    unsigned char *yuv[3] = {NULL, NULL, NULL};
    int yuv_linesize[3] = {width, width / 2, width / 2};
    yuv[0] = new unsigned char[width * height];
    yuv[1] = new unsigned char[width * height / 4];
    yuv[2] = new unsigned char[width * height / 4];
    unsigned char *rgba = new unsigned char[rgb_width * rgb_height * 4];
    int rgba_linesize = rgb_width * 4;
    ifstream ifs;
    ifs.open(YUV_FILE, ios::binary);
    if (!ifs.is_open())
    {
        return -1;
    }
    ofstream ofs;
    ofs.open(RGB_FILE, ios::binary);
    if (!ofs.is_open())
    {
        return -1;
    }
    SwsContext *yuv2rgba = nullptr;
    for (;;)
    {
        ifs.read((char *)yuv[0], width * height);
        ifs.read((char *)yuv[1], width * height / 4);
        ifs.read((char *)yuv[2], width * height / 4);
        if (ifs.gcount() < 1)
            break;
        yuv2rgba = sws_getCachedContext(
            yuv2rgba, // sws上下文，如果为nullptr那么新建，否则使用缓存，如果两个格式没有变化，那么直接返回，否者先释放
            width, height, AV_PIX_FMT_YUV420P,
            rgb_width, rgb_height, AV_PIX_FMT_RGBA,
            SWS_BILINEAR,      // 缩放算法
            NULL, NULL, NULL); // 过滤器
        if (!yuv2rgba)
        {
            cout << "sws_getCachedContext error" << endl;
            break;
        }
        unsigned char *data[1] = {rgba};
        int lines[1] = {rgba_linesize};
        int ret = sws_scale(yuv2rgba, yuv, // 源数据
                  yuv_linesize,  // 源数据尺寸
                  0, height,     // 源数据索引
                  data,      // 目标数据
                  lines);
        if (ret <= 0)
        {
            cout << "sws_scale error" << endl;
            break;
        }
        cout << "w:" <<ret<< endl;
        ofs.write((char *)rgba, rgb_width * rgb_height * 4);
    }
    delete[] yuv[0];
    delete[] yuv[1];
    delete[] yuv[2];
    delete[] rgba;
    ifs.close();
    ofs.close();
}